package com.cutefool.zero.code.core.domain;

import com.cutefool.dsl.mybatis.core.objects.BasicsDomain;
import com.fasterxml.jackson.annotation.JsonAlias;
import jakarta.annotation.Generated;
import java.sql.JDBCType;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.UnaryOperator;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.insert.InsertDSL;
import org.mybatis.dynamic.sql.insert.MultiRowInsertDSL;
import org.mybatis.dynamic.sql.update.UpdateDSL;
import org.mybatis.dynamic.sql.update.UpdateModel;

@Data
@EqualsAndHashCode(callSuper = true)
public class ModelColumn extends BasicsDomain<ModelColumn> {
    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("NAME_")
    private String name;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("DISPLAY_NAME_")
    private String displayName;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("TYPE_")
    private String type;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("DEFAULT_VALUE_")
    private String defaultValue;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("NULLABLE_")
    private Byte nullable;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("IS_UNIQUE_")
    private Byte isUnique;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("IS_SEARCH_")
    private Byte isSearch;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("IS_DEFAULT_")
    private Byte isDefault;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("IS_SYNC")
    private Byte isSync;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("TABLE_NAME_")
    private String tableName;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("LEN_")
    private Integer len;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("SCALE_")
    private Integer scale;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("REMARK_")
    private String remark;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("DBMS_ID_")
    private Long dbmsId;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("APP_ID_")
    private Long appId;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("MODEL_ID_")
    private Long modelId;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    @JsonAlias("COMPANY_ID_")
    private Long companyId;

    private static final ModelColumn instance = new ModelColumn();

    private static final Table table = new Table();

    public static ModelColumn instance() {
        return instance;
    }

    @Override
    public Table table() {
        return table;
    }

    @Override
    @SuppressWarnings("DuplicatedCode")
    public UnaryOperator<InsertDSL<ModelColumn>> insert() {
        return (InsertDSL<ModelColumn> dsl) -> {
            dsl.map(table.id).toProperty("id");
            dsl.map(table.name).toProperty("name");
            dsl.map(table.displayName).toProperty("displayName");
            dsl.map(table.type).toProperty("type");
            dsl.map(table.defaultValue).toProperty("defaultValue");
            dsl.map(table.nullable).toProperty("nullable");
            dsl.map(table.isUnique).toProperty("isUnique");
            dsl.map(table.isSearch).toProperty("isSearch");
            dsl.map(table.isDefault).toProperty("isDefault");
            dsl.map(table.isSync).toProperty("isSync");
            dsl.map(table.tableName).toProperty("tableName");
            dsl.map(table.len).toProperty("len");
            dsl.map(table.scale).toProperty("scale");
            dsl.map(table.remark).toProperty("remark");
            dsl.map(table.dbmsId).toProperty("dbmsId");
            dsl.map(table.appId).toProperty("appId");
            dsl.map(table.modelId).toProperty("modelId");
            dsl.map(table.createBy).toProperty("createBy");
            dsl.map(table.createAt).toProperty("createAt");
            dsl.map(table.updateBy).toProperty("updateBy");
            dsl.map(table.updateAt).toProperty("updateAt");
            dsl.map(table.companyId).toProperty("companyId");
            return dsl;
        };
    }

    @Override
    @SuppressWarnings("DuplicatedCode")
    public UnaryOperator<MultiRowInsertDSL<ModelColumn>> insertMultiple() {
        return (MultiRowInsertDSL<ModelColumn> dsl) -> {
            dsl.map(table.id).toProperty("id");
            dsl.map(table.name).toProperty("name");
            dsl.map(table.displayName).toProperty("displayName");
            dsl.map(table.type).toProperty("type");
            dsl.map(table.defaultValue).toProperty("defaultValue");
            dsl.map(table.nullable).toProperty("nullable");
            dsl.map(table.isUnique).toProperty("isUnique");
            dsl.map(table.isSearch).toProperty("isSearch");
            dsl.map(table.isDefault).toProperty("isDefault");
            dsl.map(table.isSync).toProperty("isSync");
            dsl.map(table.tableName).toProperty("tableName");
            dsl.map(table.len).toProperty("len");
            dsl.map(table.scale).toProperty("scale");
            dsl.map(table.remark).toProperty("remark");
            dsl.map(table.dbmsId).toProperty("dbmsId");
            dsl.map(table.appId).toProperty("appId");
            dsl.map(table.modelId).toProperty("modelId");
            dsl.map(table.createBy).toProperty("createBy");
            dsl.map(table.createAt).toProperty("createAt");
            dsl.map(table.updateBy).toProperty("updateBy");
            dsl.map(table.updateAt).toProperty("updateAt");
            dsl.map(table.companyId).toProperty("companyId");
            return dsl;
        };
    }

    @Override
    public void updateAllColumns(UpdateDSL<UpdateModel> dsl) {
        dsl.set(table.name).equalTo(this::getName)
           .set(table.displayName).equalTo(this::getDisplayName)
           .set(table.type).equalTo(this::getType)
           .set(table.defaultValue).equalTo(this::getDefaultValue)
           .set(table.nullable).equalTo(this::getNullable)
           .set(table.isUnique).equalTo(this::getIsUnique)
           .set(table.isSearch).equalTo(this::getIsSearch)
           .set(table.isDefault).equalTo(this::getIsDefault)
           .set(table.isSync).equalTo(this::getIsSync)
           .set(table.tableName).equalTo(this::getTableName)
           .set(table.len).equalTo(this::getLen)
           .set(table.scale).equalTo(this::getScale)
           .set(table.remark).equalTo(this::getRemark)
           .set(table.dbmsId).equalTo(this::getDbmsId)
           .set(table.appId).equalTo(this::getAppId)
           .set(table.modelId).equalTo(this::getModelId)
           .set(table.createBy).equalTo(this::getCreateBy)
           .set(table.createAt).equalTo(this::getCreateAt)
           .set(table.updateBy).equalTo(this::getUpdateBy)
           .set(table.updateAt).equalTo(this::getUpdateAt)
           .set(table.companyId).equalTo(this::getCompanyId);
        if(Objects.nonNull(getId())) {
            dsl.where(table.id, SqlBuilder.isEqualTo(this::getId));
        }
    }

    @Override
    public void updateSelectiveColumns(UpdateDSL<UpdateModel> dsl) {
        dsl.set(table.name).equalToWhenPresent(this::getName)
           .set(table.displayName).equalToWhenPresent(this::getDisplayName)
           .set(table.type).equalToWhenPresent(this::getType)
           .set(table.defaultValue).equalToWhenPresent(this::getDefaultValue)
           .set(table.nullable).equalToWhenPresent(this::getNullable)
           .set(table.isUnique).equalToWhenPresent(this::getIsUnique)
           .set(table.isSearch).equalToWhenPresent(this::getIsSearch)
           .set(table.isDefault).equalToWhenPresent(this::getIsDefault)
           .set(table.isSync).equalToWhenPresent(this::getIsSync)
           .set(table.tableName).equalToWhenPresent(this::getTableName)
           .set(table.len).equalToWhenPresent(this::getLen)
           .set(table.scale).equalToWhenPresent(this::getScale)
           .set(table.remark).equalToWhenPresent(this::getRemark)
           .set(table.dbmsId).equalToWhenPresent(this::getDbmsId)
           .set(table.appId).equalToWhenPresent(this::getAppId)
           .set(table.modelId).equalToWhenPresent(this::getModelId)
           .set(table.createBy).equalToWhenPresent(this::getCreateBy)
           .set(table.createAt).equalToWhenPresent(this::getCreateAt)
           .set(table.updateBy).equalToWhenPresent(this::getUpdateBy)
           .set(table.updateAt).equalToWhenPresent(this::getUpdateAt)
           .set(table.companyId).equalToWhenPresent(this::getCompanyId);
        if(Objects.nonNull(getId())) {
            dsl.where(table.id, SqlBuilder.isEqualTo(this::getId));
        }
    }

    @Override
    @SuppressWarnings("all")
    public SqlColumn[] columns() {
        return new SqlColumn[]{table.id, table.name, table.displayName, table.type, table.defaultValue, table.nullable, table.isUnique, table.isSearch, table.isDefault, table.isSync, table.tableName, table.len, table.scale, table.remark, table.dbmsId, table.appId, table.modelId, table.createBy, table.createAt, table.updateBy, table.updateAt, table.companyId};
    }

    @Override
    public Map<String, SqlColumn<?>> columnsMap() {
        Map<String, SqlColumn<?>> maps = new LinkedHashMap<>(22);
        maps.put("id", table.id);
        maps.put("name", table.name);
        maps.put("displayName", table.displayName);
        maps.put("type", table.type);
        maps.put("defaultValue", table.defaultValue);
        maps.put("nullable", table.nullable);
        maps.put("isUnique", table.isUnique);
        maps.put("isSearch", table.isSearch);
        maps.put("isDefault", table.isDefault);
        maps.put("isSync", table.isSync);
        maps.put("tableName", table.tableName);
        maps.put("len", table.len);
        maps.put("scale", table.scale);
        maps.put("remark", table.remark);
        maps.put("dbmsId", table.dbmsId);
        maps.put("appId", table.appId);
        maps.put("modelId", table.modelId);
        maps.put("createBy", table.createBy);
        maps.put("createAt", table.createAt);
        maps.put("updateBy", table.updateBy);
        maps.put("updateAt", table.updateAt);
        maps.put("companyId", table.companyId);
        return maps;
    }

    @Override
    public SqlColumn<Long> id() {
        return table.id;
    }

    public static final class Table extends org.mybatis.dynamic.sql.AliasableSqlTable<Table> {
        public final SqlColumn<Long> id = column("ID_", JDBCType.BIGINT);

        public final SqlColumn<String> name = column("NAME_", JDBCType.VARCHAR);

        public final SqlColumn<String> displayName = column("DISPLAY_NAME_", JDBCType.VARCHAR);

        public final SqlColumn<String> type = column("TYPE_", JDBCType.VARCHAR);

        public final SqlColumn<String> defaultValue = column("DEFAULT_VALUE_", JDBCType.VARCHAR);

        public final SqlColumn<Byte> nullable = column("NULLABLE_", JDBCType.TINYINT);

        public final SqlColumn<Byte> isUnique = column("IS_UNIQUE_", JDBCType.TINYINT);

        public final SqlColumn<Byte> isSearch = column("IS_SEARCH_", JDBCType.TINYINT);

        public final SqlColumn<Byte> isDefault = column("IS_DEFAULT_", JDBCType.TINYINT);

        public final SqlColumn<Byte> isSync = column("IS_SYNC", JDBCType.TINYINT);

        public final SqlColumn<String> tableName = column("TABLE_NAME_", JDBCType.VARCHAR);

        public final SqlColumn<Integer> len = column("LEN_", JDBCType.INTEGER);

        public final SqlColumn<Integer> scale = column("SCALE_", JDBCType.INTEGER);

        public final SqlColumn<String> remark = column("REMARK_", JDBCType.VARCHAR);

        public final SqlColumn<Long> dbmsId = column("DBMS_ID_", JDBCType.BIGINT);

        public final SqlColumn<Long> appId = column("APP_ID_", JDBCType.BIGINT);

        public final SqlColumn<Long> modelId = column("MODEL_ID_", JDBCType.BIGINT);

        public final SqlColumn<Long> createBy = column("CREATE_BY_", JDBCType.BIGINT);

        public final SqlColumn<LocalDateTime> createAt = column("CREATE_AT_", JDBCType.TIMESTAMP);

        public final SqlColumn<Long> updateBy = column("UPDATE_BY_", JDBCType.BIGINT);

        public final SqlColumn<LocalDateTime> updateAt = column("UPDATE_AT_", JDBCType.TIMESTAMP);

        public final SqlColumn<Long> companyId = column("COMPANY_ID_", JDBCType.BIGINT);

        public Table() {
            super("CUTE_MODEL_COLUMN", Table::new);
        }
    }
}